#!/usr/bin/python3
"""Spawn a jq subprocess and wrap some IO interactions for it.

jq seems unable to
 - open an arbitrary file (slurp)
 - emit a string on stdout without new line (readline)
"""
from json import JSONDecodeError, dumps, loads
from os import environ
from os.path import dirname, join, realpath
from subprocess import PIPE, Popen
from sys import argv

rundir = dirname(realpath(__file__))
with Popen(args=['/usr/bin/jq',
                 '--argjson', 'DEBUG', 'false',
                 '-nrM',  # --null-input --raw-output --monochrome-output
                 '-L', rundir,
                 '-f', join(rundir, environ.get('STEP', 'stepA_mal') + '.jq'),
                 '--args'] + argv[1:],
           stdin=PIPE, stderr=PIPE, encoding='utf-8',
           ) as proc:
    assert proc.stderr is not None  # for mypy
    for received in proc.stderr:
        try:
            as_json = loads(received)
        except JSONDecodeError:
            print(f'JQ STDERR: {received}', end=None)
        else:
            match as_json:
                case ['DEBUG:', ['display', str(message)]]:
                    # While at it, provide a way to immediately print to
                    # stdin for DEBUG-EVAL, println and prn (jq is able to
                    # output to stderr, but *we* are already piping it).
                    print(message)
                    # Jq waits for this signal to go on, so that its own
                    # output is not mixed with our one.
                    print('null', file=proc.stdin, flush=True)
                case ['DEBUG:', ['readline', str(prompt)]]:
                    try:
                        data = input(prompt)
                    except EOFError:
                        break                   # Expected end of this script
                    print(dumps(data), file=proc.stdin, flush=True)
                case ['DEBUG:', ['slurp', str(fname)]]:
                    with open(fname, 'r', encoding='utf-8') as file_handler:
                        data = file_handler.read()
                    print(dumps(data), file=proc.stdin, flush=True)
                case _:
                    # Allow normal debugging information for other purposes.
                    print(f'JQ STDERR: {received}', end=None)
print()
